package biz

import (
	"amount1/internal/http_resty"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gogf/gf/util/gconv"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/trace"
	"net/http"
)

// POST 请求
func (a *Amount1BizStruct) httpPost(ctx context.Context, name string) error {
	ctx, span := otel.Tracer("BIZ").Start(ctx, "httpPostBiz", trace.WithSpanKind(trace.SpanKindInternal))
	defer span.End()

	meta := http_resty.HttpRequestMeta{
		Name: name,
	}

	// Notice 这里为了打印转的
	//paramsStr, errParams := jsoniter.MarshalToString(meta)
	//if errParams != nil {
	//	return errors.New(fmt.Sprintf("jsonMarshal失败! err: %v", errParams))
	//}
	fmt.Println("POST发送的请求体为: ", gconv.String(meta))

	// Notice 实际中最好用resp转结果，我发现有时候SetResult不准，会获取到空数据！
	//result := make(map[string]any)
	resp, errResp := a.httpRestyClient.R().
		SetContext(ctx).
		EnableTrace().
		SetHeader("Content-Type", "application/json;charset=utf-8").
		SetBody(meta). // Notice 可以直接把结构体放到body中
		//SetResult(&result).
		Post("http://127.0.0.1:9099/index")

	if errResp != nil {
		// trace
		span.SetAttributes(
			attribute.String("url", "http://127.0.0.1:9099/index"),
			attribute.String("httpResp", gconv.String(resp)),
			attribute.String("httpError", gconv.String(errResp)),
		)
		return errors.New(fmt.Sprintf("发送POST请求失败! err: %v", errResp))
	}

	// Notice 注意: errResp 不能cover住 404 这个错误!最好单独判断下返回的错误码!防止接口404后面处理异常了
	// statusCode
	if resp.StatusCode() != http.StatusOK {
		// trace
		span.SetAttributes(
			attribute.String("url", "http://127.0.0.1:9099/index"),
			attribute.String("httpResp", gconv.String(resp)),
			attribute.String("statusCode", gconv.String(resp.StatusCode())),
		)
		return errors.New(fmt.Sprintf("POST请求返回的错误码: %v, 请求的URL: %v", resp.StatusCode(), "http://127.0.0.1:9099/index"))
	}

	// trace
	span.SetAttributes(attribute.String("httpRequestTraceInfo", gconv.String(resp.Request.TraceInfo())), attribute.String("httpResponse", gconv.String(resp)))

	fmt.Println("respBody: ", gconv.String(resp.Body()))

	// 解析结果 Notice 注意使用 resp.Body() 解析结果
	result := make(map[string]any) // Notice 当然也可以使用定义好的 结构体对象 解析结果
	errUnmarshal := json.Unmarshal(resp.Body(), &result)
	if errUnmarshal != nil {
		return errors.New(fmt.Sprintf("errUnmarshal: %v", errUnmarshal))
	}

	fmt.Println("Unmarshal解析的结果: ", result)

	return nil
}

// GET 请求
func (a *Amount1BizStruct) httpGet(ctx context.Context, name string) error {
	ctx, span := otel.Tracer("BIZ").Start(ctx, "httpGetBiz", trace.WithSpanKind(trace.SpanKindInternal))
	defer span.End()

	// Notice 实际中最好用resp转结果，我发现有时候SetResult不准，会获取到空数据！
	resp, errResp := a.httpRestyClient.R().
		// Notice GET请求这样发送参数
		SetQueryParams(map[string]string{
			"name": name,
		}).
		SetContext(ctx).
		EnableTrace().
		Get("http://127.0.0.1:9099/index")

	if errResp != nil {
		// trace
		span.SetAttributes(
			attribute.String("url", "http://127.0.0.1:9099/index"),
			attribute.String("httpResp", gconv.String(resp)),
			attribute.String("httpError", gconv.String(errResp)),
		)
		return errors.New(fmt.Sprintf("发送GET请求失败! err: %v", errResp))
	}

	// Notice 注意: errResp 不能cover住 404 这个错误!最好单独判断下返回的错误码!防止接口404后面处理异常了
	// statusCode
	if resp.StatusCode() != http.StatusOK {
		// trace
		span.SetAttributes(
			attribute.String("url", "http://127.0.0.1:9099/index"),
			attribute.String("httpResp", gconv.String(resp)),
			attribute.String("statusCode", gconv.String(resp.StatusCode())),
		)
		return errors.New(fmt.Sprintf("GET请求返回的错误码: %v, 请求的URL: %v", resp.StatusCode(), "http://127.0.0.1:9099/index"))
	}

	// Notice 设置trace
	span.SetAttributes(attribute.String("httpRequestTraceInfo", gconv.String(resp.Request.TraceInfo())), attribute.String("httpResponse", gconv.String(resp)))

	fmt.Printf("GET收到的响应为: %T, %v \n", resp, resp)

	// TODO 解析结果跟 POST请求的方法一样，使用 resp.Body() 这里忽略了...

	return nil
}
